using System.Reflection;
using System.Xml.Linq;
using Microsoft.EntityFrameworkCore;
using StudentVideo.Data.Entities;

namespace StudentVideo.Data.Extensions;

public static class ModelBuilderExtensions {
   /// <summary>
   /// xml注释转换为数据库注释
   /// </summary>
   /// <param name="modelBuilder"></param>
   /// <param name="assembly"></param>
   public static void ApplyXmlComments(this ModelBuilder modelBuilder, Assembly assembly) {
      var assemblyName = assembly.GetName().Name;
      var moduleName = modelBuilder.GetType().Name;

      var xmlFile = $"{assemblyName}.xml";
      var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

      if (!File.Exists(xmlPath))
         return;

      var xmlDoc = XDocument.Load(xmlPath);
      var xmlMembers = xmlDoc.Descendants("member");

      // 获取基础字段的注释
      var baseType = typeof(BaseEntity);
      var baseProps = baseType.GetProperties();

      Dictionary<string, string> baseComments = [];
      foreach (var prop in baseProps) {
         var name = $"P:{assemblyName}.Entities.BaseEntity.{prop.Name}";

         var comment = xmlMembers.FirstOrDefault(e => e.Attribute("name")?.Value == name)?.Value.Trim();

         if (string.IsNullOrEmpty(comment))
            continue;

         baseComments.Add(prop.Name, comment);
      }

      // 获取 xml 文档并写入注释
      var entityTypes = modelBuilder.Model.GetEntityTypes();
      foreach (var entityType in entityTypes) {
         // 只处理当前程序集中的类型
         if (entityType.ClrType.Assembly != assembly)
            continue;

         // 获取并设置数据表的注释
         var type = entityType.ClrType;
         var typeMemberName = $"T:{assemblyName}.Entities.{type.Name}";
         var typeComments = xmlMembers
            .FirstOrDefault(m => m.Attribute("name")?.Value == typeMemberName)
            ?.Element("summary")
            ?.Value
            .Trim();

         if (!string.IsNullOrEmpty(typeComments)) {
            entityType.SetComment(typeComments);
         }

         // 获取并设置字段的注释
         foreach (var property in entityType.GetProperties()) {
            var propMemberName = $"P:{property.PropertyInfo?.ReflectedType?.FullName}.{property.Name}";
            var propComments = xmlMembers
               .FirstOrDefault(m => m.Attribute("name")?.Value == propMemberName)
               ?.Element("summary")
               ?.Value
               .Trim();

            if (!string.IsNullOrEmpty(propComments)) {
               property.SetComment(propComments);
               continue;
            }

            // 当不存在注释时，检查是否属于 BaseEntity
            var baseComment = baseComments.GetValueOrDefault(property.Name);
            if (baseComment == null)
               continue;

            property.SetComment(baseComment);
         }
      }
   }
}
